package com.github.tommas.admintpl.service;

import com.github.tommas.admintpl.bean.model.User;
import com.github.tommas.admintpl.bean.vo.PaginationQuery;
import com.github.tommas.admintpl.bean.vo.SearchUserParam;
import com.github.tommas.admintpl.cache.CacheManager;
import com.github.tommas.admintpl.common.PaginationData;
import com.github.tommas.admintpl.config.CacheConfiguration;
import com.github.tommas.admintpl.dao.UserMapper;
import com.github.tommas.admintpl.mybatis.Context;
import org.apache.shiro.crypto.hash.Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

@Service
public class UserService {
    @Autowired
    AccountService accountService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    @Qualifier(CacheConfiguration.DEPT_ISOLATION_CACHE)
    private CacheManager<List<Integer>> entityIsolationCache;

    public PaginationData<User> getUserList(PaginationQuery<SearchUserParam> pq) {
        return PaginationData.createFromQuery(
                pq, () -> userMapper.searchUserList());
    }

    public User findUser(Integer userId) {
        return userMapper.findUser(userId);
    }

    public User createUser(User user) {
        String password = user.getPassword();
        if (StringUtils.hasLength(password)) {
            Hash hash = accountService.getHashedPassword(password, user.getUsername());
            user.setPassword(hash.toHex());
        }

        userMapper.createUser(Context.insertContext(user), user);
        return user;
    }

    public User updateUser(Integer id, User user) {
        user.setId(id);
        int result = userMapper.updateUser(Context.updateContext(user), user);
        if (result == 0) {
            return null;
        }

        return user;
    }

    @Transactional
    public boolean deleteUser(Integer id) {
        userMapper.deleteUserRoles(id);
        int result = userMapper.deleteUser(Context.deleteContext(), id);
        return result != 0;
    }

    @Transactional
    public boolean assignRoles(Integer userId, List<Integer> roleIds) {
        userMapper.deleteUserRoles(userId);
        return userMapper.insertUserRoles(userId, roleIds) > 0;
    }

    @Transactional
    public boolean assignEntity(Integer userId, List<Integer> entityIds) {
        // invalidate cache
        entityIsolationCache.getCache(userId.toString()).invalidate();

        userMapper.deleteUserEntities(userId);
        return userMapper.insertUserEntities(userId, entityIds) > 0;
    }

    public List<Integer> getUserEntities(Integer userId) {
        return userMapper.findUserEntities(userId);
    }
}
